﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace Corona
{
	/// <summary>
	/// IconManager.xaml 的交互逻辑
	/// </summary>
	public partial class IconManager
	{
        public List<Icon> IconCollection = new List<Icon>();
        public List<TagIcon> TagIconCollection = new List<TagIcon>();
        public List<Corona.TagPresent.TagInfo> SelectedIcons = new List<Corona.TagPresent.TagInfo>();
        public List<ResourceIcon> ResourceIconCollection = new List<ResourceIcon>();
        public List<RelationLine> RelationConllection = new List<RelationLine>();

        //绘制选区使用
        private Point StartPoint = new Point();
        private Point IconPoint = new Point();
        private bool IsDrawingSelector = false;
        //隐藏选区动画
        Storyboard hideSelector = new Storyboard();

		public IconManager()
		{
			this.InitializeComponent();
        }

        #region Add new icon
        public void AddNewIcon()
        {
            Icon icon = new Icon();
            ParentCanvas.Children.Add(icon);
            IconCollection.Add(icon);
        }
        public void AddNewTag()
        {
            TagIcon tagicon = new TagIcon();
            ParentCanvas.Children.Add(tagicon);
            TagIconCollection.Add(tagicon);
            IconCollection.Add(tagicon);
        }
        public void AddNewResource()
        {
            ResourceIcon resourceicon = new ResourceIcon();
            ParentCanvas.Children.Add(resourceicon);
            ResourceIconCollection.Add(resourceicon);
            IconCollection.Add(resourceicon);
        }
        #endregion

        #region Remove icon
        public void RemoveIcon(Icon icon)
        {
            ParentCanvas.Children.Remove(icon);
            IconCollection.Remove(icon);
            if (icon is TagIcon)
                TagIconCollection.Remove(icon as TagIcon);
            //else if
        }
        public void RemoveTag(TagIcon tagicon)
        {
            ParentCanvas.Children.Remove(tagicon);
            IconCollection.Remove(tagicon);
            TagIconCollection.Remove(tagicon);
        }
        public void RemoveResource(ResourceIcon resourceicon)
        {
            ParentCanvas.Children.Remove(resourceicon);
            IconCollection.Remove(resourceicon);
            ResourceIconCollection.Remove(resourceicon);
        }
        #endregion

        #region Clear icon
        public void ClearIcon()
        {
            ParentCanvas.Children.Clear();
            IconCollection.Clear();
            TagIconCollection.Clear();
            ResourceIconCollection.Clear();
        }
        public void ClearTag()
        {
            foreach (TagIcon tagicon in TagIconCollection)
            {
                ParentCanvas.Children.Remove(tagicon);
                IconCollection.Remove(tagicon);
            }
            TagIconCollection.Clear();
        }
        public void ClearResource()
        {
            foreach (ResourceIcon resourceicon in ResourceIconCollection)
            {
                ParentCanvas.Children.Remove(resourceicon);
                IconCollection.Remove(resourceicon);
            }
            ResourceIconCollection.Clear();
        }
        #endregion

        #region Selector FINISH!
        public event EventHandler<MouseButtonEventArgs> StartSelectEvent;
        /// <summary>
        /// 开始进行选区选择
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StartSelect(object sender, MouseButtonEventArgs e)
        {
            IsDrawingSelector = true;
            Canvas.SetZIndex(IconSelector, Int32.MaxValue);

            if (StartSelectEvent != null)
                StartSelectEvent(this, e);

            IconSelector.ClearSelector();
            SelectedIcons.Clear();

            hideSelector.Stop();
            IconSelector.Visibility = Visibility.Visible;
            IconSelector.Opacity = 1;

            StartPoint = e.GetPosition(ParentCanvas);
            IconSelector.InitialSelector(StartPoint);
        }

        public event EventHandler<Corona.TagPresent.TagSelectEventArgs> OnSelectingEvent;
        /// <summary>
        /// 选择过程中处理的方法
        /// </summary>
        /// <param name="sender"></param>
        private void OnSelecting(object sender)
        {
            SelectedIcons.Clear();
            if (IsDrawingSelector && CanCreateLine == CreateLineState.NotBegin)
            {
                foreach (TagIcon icon in TagIconCollection)
                {
                    IconPoint = icon.Position;
                    for (int i = 0; i < IconSelector.SelectorPoints.Count - 2; i++)
                    {
                        if (IsInLine(IconSelector.SelectorPoints[i], IconSelector.SelectorPoints[i + 1], IconPoint, IconSelector.SelectorPoints[i + 2]))
                            icon.CrossCount++;
                    }
                    if (IconSelector.SelectorPoints.Count >= 2)
                    {
                        if (IsInLine(IconSelector.SelectorPoints[IconSelector.SelectorPoints.Count - 2], IconSelector.SelectorPoints[IconSelector.SelectorPoints.Count - 1], IconPoint, IconSelector.SelectorPoints[0]))
                            icon.CrossCount++;
                        if (IsInLine(IconSelector.SelectorPoints[IconSelector.SelectorPoints.Count - 1], IconSelector.SelectorPoints[0], IconPoint, IconSelector.SelectorPoints[1]))
                            icon.CrossCount++;
                    }
                    if ((icon.CrossCount % 2) != 0)
                        SelectedIcons.Add(icon as Corona.TagPresent.TagInfo);
                    icon.CrossCount = 0;
                }
                if (OnSelectingEvent != null)
                    OnSelectingEvent(this, new Corona.TagPresent.TagSelectEventArgs(SelectedIcons));
            }
        }
        
        public event EventHandler<Corona.TagPresent.TagSelectEventArgs> FinishSelectEvent;
        /// <summary>
        /// 结束选择时候的处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FinishSelect(object sender, MouseButtonEventArgs e)
        {
            hideSelector = this.FindResource("HideSelector") as Storyboard;
            hideSelector.Begin();
            IsDrawingSelector = false;

            if (FinishSelectEvent != null)
                FinishSelectEvent(this, new Corona.TagPresent.TagSelectEventArgs(SelectedIcons));
        }

        /// <summary>
        /// 判断一个点是否在一条线段的右侧
        /// </summary>
        /// <param name="pt1"></param>
        /// <param name="pt2"></param>
        /// <param name="pt"></param>
        /// <param name="pt3"></param>
        /// <returns></returns>
        private bool IsInLine(Point pt1, Point pt2, Point pt, Point pt3)
        {
            if (pt1.Y == pt2.Y && pt1.Y == pt.Y)
            {
                if ((pt.X >= pt1.X || pt.X >= pt2.X) && pt3.Y != pt.Y) return true;
                else return false;
            }
            else if (pt.Y == pt2.Y && pt1.Y != pt2.Y)
            {
                if ((pt1.Y > pt.Y && pt3.Y < pt.Y) || (pt1.Y < pt.Y && pt3.Y > pt.Y))
                {
                    if (pt.X >= pt1.X + (pt.Y - pt1.Y) * (pt2.X - pt1.X) / (pt2.Y - pt1.Y)) return true;
                    else return false;
                }
                else return false;
            }
            else if (pt1.Y != pt2.Y && pt.Y < Math.Max(pt1.Y, pt2.Y) && pt.Y > Math.Min(pt1.Y, pt2.Y))
            {
                if (pt.X >= pt1.X + (pt.Y - pt1.Y) * (pt2.X - pt1.X) / (pt2.Y - pt1.Y)) return true;
                else return false;
            }
            else return false;
        }
        #endregion

        private Line CreateRL = new Line();
        /// <summary>
        /// 判断创建关系线的状态（没有开始创建、已经获得StartIcon、创建完毕）
        /// </summary>
        private CreateLineState CanCreateLine = CreateLineState.NotBegin;
        /// <summary>
        /// 创建关系线的起始点
        /// </summary>
        private Icon StartIcon;
        /// <summary>
        /// 创建关系线的结束点
        /// </summary>
        private Icon EndIcon;
        /// <summary>
        /// 开始或者结束创建关系线
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StartOrFinishCreateLine(object sender, MouseButtonEventArgs e)
        {
            this.ParentCanvas.Children.Remove(CreateRL);
            CanCreateLine = CanCreateLine == CreateLineState.WaitForEnd ? CreateLineState.FinishCreate : CreateLineState.WaitForEnd;

            if (CanCreateLine == CreateLineState.WaitForEnd)
            {
                CreateRL.Visibility = Visibility.Visible;
                StartIcon = sender as Icon;
                CreateRL.X1 = (StartIcon).Position.X;
                CreateRL.Y1 = (StartIcon).Position.Y;
                CreateRL.X2 = e.GetPosition(ParentCanvas).X;
                CreateRL.Y2 = e.GetPosition(ParentCanvas).Y;
                CreateRL.Stroke = Brushes.Orange;
                CreateRL.Opacity = 0.8;
                CreateRL.StrokeThickness = 1;
                CreateRL.StrokeDashArray = new DoubleCollection(new double[] { 4, 2 });
                ParentCanvas.Children.Add(CreateRL);
                Canvas.SetZIndex(CreateRL, Int32.MaxValue);
            }
            else if (CanCreateLine == CreateLineState.FinishCreate)
            {
                EndIcon = sender as Icon;
                CreateRL.Visibility = Visibility.Hidden;
                if (StartIcon != EndIcon)
                {
                    int i = 0;
                    foreach (RelationLine relationLine in RelationConllection)
                    {
                        if (relationLine.StartIcon == StartIcon && relationLine.EndIcon == EndIcon)
                        {
                            MessageBox.Show("There has been a same RELATIONLINE!");
                            i++;
                        }
                    }
                    if (i == 0)
                    {
                        ParentCanvas.Children.Add(new RelationLine(StartIcon, EndIcon));
                    }
                    CanCreateLine = CreateLineState.NotBegin;
                    ParentCanvas.Children.Remove(CreateRL);
                }
                else
                {
                    CanCreateLine = CreateLineState.NotBegin;
                    ParentCanvas.Children.Remove(CreateRL);
                }
                StartIcon = null;
                EndIcon = null;
            }
        }
        /// <summary>
        /// 创建关系线时末端跟踪鼠标
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CreatingLine(object sender, MouseEventArgs e)
        {
            if (!IsDrawingSelector && CanCreateLine == CreateLineState.WaitForEnd)
            {
                Point mousept = new Point();
                mousept = e.GetPosition(ParentCanvas);
                double d = Math.Sqrt(Math.Pow(mousept.X - CreateRL.X1, 2) + Math.Pow(mousept.Y - CreateRL.Y1, 2));
                if (d != 0)
                {
                    this.CreateRL.X2 = mousept.X - 5 * (mousept.X - CreateRL.X1) / d;
                    this.CreateRL.Y2 = mousept.Y - 5 * (mousept.Y - CreateRL.Y1) / d;
                }
                else
                {
                    this.CreateRL.X2 = mousept.X;
                    this.CreateRL.Y2 = mousept.Y;
                }
            }
        }

        Point startingMPos = new Point();
        Point endingMPos = new Point();
        private bool posChanged = false;
        private bool? moving = null;
        private double dx;
        private double dy;
        private void CanvasDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            moving = false;
            ParentCanvas.Cursor = Cursors.Arrow;
            startingMPos = e.GetPosition(ParentCanvas);
        }
        private void CanvasMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if ((moving != null) && (moving == false))
            {
                posChanged = true;
                ParentCanvas.Cursor = Cursors.ScrollAll;
            }

            if (posChanged)
            {
                endingMPos = e.GetPosition(ParentCanvas);

                dx = startingMPos.X - endingMPos.X;
                dy = startingMPos.Y - endingMPos.Y;

                double newPosY = canvasScroller.VerticalOffset + dy;
                double newPosX = canvasScroller.HorizontalOffset + dx;
                canvasScroller.ScrollToHorizontalOffset(newPosX);
                canvasScroller.ScrollToVerticalOffset(newPosY);
            }
        }

        private void CanvasUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            posChanged = false;
            moving = true;
            ParentCanvas.Cursor = Cursors.Arrow;
        }

        #region ENUM
        private enum CreateLineState
        {
            WaitForEnd,
            NotBegin,
            FinishCreate
        }
        #endregion
    }
}